
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "hj212message.h"
#include "types.h"
#include "hj212parser.h"
#include "util.h"

// typedef struct _tag_hj212_parser_t {
//     Message* (*readmem)(unsigned char* mem, unsigned int size);
//     Message* (*readfd)(int fd);
//     void (*reset)(void);
// } HJ212Parser;

#define HJ212_PARSER_MSG_LENGTH_MAX             (1031)
// ##0078QN=00010101000000000;ST=91;CN=9014;PW=123456;MN=abcdef123456789;Flag=4;CP=&&&&84C1
typedef struct msg_parser
{
    SocketParser parser;
    int header;      // 标识消息头是否解析成功
    int need;        // 标识还需要多少字节才能完成解析
    int length;
    char msg[HJ212_PARSER_MSG_LENGTH_MAX];   // 解析中的协议消息（半成品）
} MsgParser;


static int _to_recv(int fd, char* buf, int size)
{
    int retry = 0;
    int i = 0;

    while( i < size )
    {
        int len = read(fd, buf + i, size - i);
        
        if( len > 0 )
        {
            i += len;
        }
        else if( len < 0 )
        {
            break;
        }
        else
        {
            if( retry++ > 5 )
            {
                break;
            }

            usleep(200 * 1000);
        }
    }

    printf("_to_recv: %d %d\n", i, size);
    return i;
}


//##0078QN=00010101000000000;ST=91;CN=9014;PW=123456;MN=abcdef123456789;Flag=4;CP=&&&&84C1
static int _to_mid_state(MsgParser* p, char* buf)
{
    char *endptr;
    unsigned short num;
    char numstr[6] = {0};
  
    if ( '#' == buf[0] && '#' == buf[1] )
    {
        strncpy(numstr, buf+2, 4);
        numstr[4] = 0;

        num = strtol(numstr, &endptr, 10);
        
        if( *endptr == '\0' )
        {
            p->header = 1;
            p->need = num + 6; // xxxx 校验  \r\n
            p->length = p->need;
        }
    }
    printf("_to_mid_state %d\n", p->header);
    return p->header;
}

#define HJ212_HEADER_LENGTH                 6

static void _init_state(MsgParser* p)
{
    p->header = 0;
    p->need = HJ212_HEADER_LENGTH;
    p->length = HJ212_HEADER_LENGTH;
    memset(p->msg, 0, HJ212_PARSER_MSG_LENGTH_MAX);

}

//##0078QN=00010101000000000;ST=91;CN=9014;PW=123456;MN=abcdef123456789;Flag=4;CP=&&&&84C1
/*
    char* qn;
    unsigned char st;
    unsigned short cn;
    char* pwd;
    char* mn;
    unsigned char flag;
    int length;
    unsigned char payload[];
*/

static char* _str_parser(char* str, char* start, char* end)
{
    char* ret = NULL;
    char* ptr = strstr(str, start);
    if ( ptr )
    {
        char* strend = strstr(ptr, end);
        if ( strend )
        {
            int len = strend - ptr - strlen(start);
           
            if ( len > 0 )
            {
                ret = (char*)malloc(len + 1);
                strncpy(ret, ptr + strlen(start), len);
                ret[len] = 0;
            }
        }
    }

    return ret;
}

static HJ212Msg* _to_last_state(MsgParser* p)
{
    HJ212Msg* ret = NULL;
    char *endptr;
    unsigned short crcval = 0;
    char crc[5] = { 0 };
    
    if( p->header && !p->need )
    {
        char* cp = strstr(p->msg, "CP=&&");
        if ( cp )
        {
            char* end = strstr(cp+5, "&&");
            if ( end )
            {
                strncpy(crc, end+2, 4);
                crc[4] = 0;
                crcval = strtol(crc, &endptr, 16);
                if ( *endptr == 0 )
                {
                    if ( crcval == hj212_crc16(p->msg, ((end+2) - p->msg)) )
                    {
                        int msgleng = end - (cp+5);
                        char msgstr[1024] = { 0 };
                        char qnstr[20] = { 0 };
                        char pwdstr[9] = { 0 };
                        char mnstr[27] = { 0 };
                      
                        char* qn = _str_parser(p->msg, "QN=", ";");
                        char* st = _str_parser(p->msg, "ST=", ";");
                        char* cn = _str_parser(p->msg, "CN=", ";");
                        char* pwd = _str_parser(p->msg, "PW=", ";");
                        char* mn = _str_parser(p->msg, "MN=", ";");
                        char* flag = _str_parser(p->msg, "Flag=", ";");

                        if ( qn && st && cn && mn && flag )
                        {
                            strcpy(qnstr, qn);
                            strcpy(mnstr, mn);
                            if ( pwd )
                                strcpy(pwdstr, pwd);
                            else
                                memset(pwdstr, 0, 9);

                            strncpy(msgstr, cp+5, msgleng);
                            msgstr[msgleng] = '\0';
                            int stval = atoi(st);
                            int cnval = atoi(cn);
                            int flagval = atoi(flag);
                            if ( pwd )
                                ret = HJ212_create_message(qnstr, stval, cnval, pwdstr, mnstr, flagval, msgstr, msgleng);
                            else
                                ret = HJ212_create_message(qnstr, stval, cnval, NULL, mnstr, flagval, msgstr, msgleng);
                        }
                        
                        free(qn);
                        free(st);
                        free(cn);
                        free(pwd);
                        free(mn);
                        free(flag);
                    }
                }
            }
        }
    } 

    return ret;
}

static HJ212Msg* _hj212parser_readfd(HJ212Parser* parser, int fd)
{
    HJ212Msg* ret = NULL;
    MsgParser* p = (MsgParser*)parser;
    static char headstr[8] = { 0 };
    printf("readfd %d  %p\n", fd, p);
    if( (fd != -1) && p )
    {
        if( !p->header )
        {
            int offset = p->length - p->need;
            int len = _to_recv(fd, (char*)headstr + offset, p->need);

            if( len == p->need )
            {
                if( _to_mid_state(p, headstr) )
                {
                    ret = _hj212parser_readfd(p, fd);
                }
                else
                {  
                    _init_state(p);
                }
            }
            else
            {
                p->need -= len;
            }
        }
        else
        {
            int offset = p->length - p->need;
            int len = _to_recv(fd, p->msg + offset, p->need);

            p->need -= len;
         
            if( (ret = _to_last_state(p)) != NULL )
            {
                _init_state(p);
            }
        }
    }
  
    return ret;
}

static HJ212Msg* _hj212parser_readmem(HJ212Parser* parser,unsigned char* mem, unsigned int size)
{
    HJ212Msg* msg = NULL;

    return msg;
}

static void _hj212parser_reset(void)
{

}

HJ212Parser* hj212parser_new(void)
{
    MsgParser* parser = (MsgParser*)malloc(sizeof(MsgParser));

    if ( parser )
    {
        parser->parser.readfd = _hj212parser_readfd;
        parser->parser.readmem = _hj212parser_readmem;
        parser->parser.reset = _hj212parser_reset;

        _init_state(parser);
    }

    return (HJ212Parser*)parser;
}


HJ212Parser* hj212parser_destroy(HJ212Parser* parser)
{
    if ( parser ) free(parser);
    
    return NULL;
}